#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>

using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)
template<typename T, typename ...ARGS>
struct ARG {
    typedef T type;
    typedef ARG<ARGS...> rest;
};

template<typename T>
struct ARG<T> {
    typedef T type;
};

template<typename T, typename ...ARGS>
class Test {
public:
    T operator()(typename ARG<ARGS...>::type a, typename ARG<ARGS...>::rest::type b) {
        return a + b;
    }
};

int main() {
    Test<int, int, int> t1; // 返回类型为int，接受2个参数，分别为int和int
    Test<double, double, int> t2; // 返回类型为double，接受2个参数，分别为double和int
    cout << t1(3, 4) << endl;
    cout << t2(3.5, 4) << endl;
    return 0;
}

ENDS(test1)


BEGINS(test2)
    template<typename T, typename ...ARGS>
    struct ARG {
        typedef T type;
        typedef ARG<ARGS...> rest;
    };

    template<typename T>
    struct ARG<T> {
        typedef T type;
        typedef T ftype;
    };

    template<typename T, typename ...ARGS>
    class Test {
    public:
        T operator()(typename ARG<ARGS...>::type a, typename ARG<ARGS...>::rest::ftype b) {
            return a + b;
        }
    };

    int main() {
        Test<int, int, int> t1; // 返回类型为int，接受2个参数，分别为int和int
        Test<double, double, int> t2; // 返回类型为double，接受2个参数，分别为double和int
//         Test<double, int, int, int> t3;
        cout << t1(3, 4) << endl;
        cout << t2(3.5, 4) << endl;
        return 0;
    }
ENDS(test2)

BEGINS(test3)
    template<int N, typename T, typename ...ARGS>
    struct ARG {
        typedef typename ARG<N - 1, T, ARGS...>::type type;
    };

    template<typename T, typename ...ARGS>
    struct ARG<1, T, ARGS...> {
          typedef T type;
    };

//    template<typename T>
//    struct ARG<1, T> {
//        typedef T type;
//    };

    template<typename T, typename ...ARGS>
    struct NUM_ARGS {
        static constexpr int r = NUM_ARGS<ARGS...>::r + 1;
    };

    template<typename T>
    struct NUM_ARGS<T> {
        static constexpr int r = 1;
    };

    template<int N>
    struct Zero {
        typedef int no;
    };

    template<>
    struct Zero<0> {
        typedef int yes;
    };

    template<typename T, typename ...ARGS> class Test;
    template<typename T, typename ...ARGS>
    class Test<T(ARGS...)> {
    public:
        typedef typename Zero<2 - NUM_ARGS<ARGS...>::r>::yes TYPE_NUM_2;
        T operator()(
                typename ARG<1, ARGS...>::type a,
                typename ARG<2, ARGS...>::type b) {
            return a + b;
        }
    };

    int main() {
//        cout << NUM_ARGS<int, int, int, int>::r << endl;
//        cout << NUM_ARGS<int, int, int>::r << endl;
//        cout << NUM_ARGS<int, int>::r << endl;
        Test<int(int, int)> t1;
        cout << t1(3, 5) << endl;
//        Test<bool(int, int, int)> t2;

        return 0;
    }

ENDS(test3)

int main() {
    test3::main();

}